using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;

namespace Beetle.Clients;

public class SyncNode : IDisposable
{
	public class Connection : IDisposable
	{
		private Exception a;

		[CompilerGenerated]
		private SyncNode b;

		[CompilerGenerated]
		private ISyncChannel c;

		internal SyncNode Pool
		{
			[CompilerGenerated]
			get
			{
				return b;
			}
			[CompilerGenerated]
			set
			{
				b = value;
			}
		}

		public ISyncChannel Channel
		{
			[CompilerGenerated]
			get
			{
				return c;
			}
			[CompilerGenerated]
			internal set
			{
				c = value;
			}
		}

		public object Send(object data)
		{
			try
			{
				return Channel.Send(data);
			}
			catch (Exception ex)
			{
				throw a = ex;
			}
		}

		public T Send<T>(object data)
		{
			return (T)Send(data);
		}

		public void SendOnly(object data)
		{
			try
			{
				Channel.SendOnly(data);
			}
			catch (Exception ex)
			{
				throw a = ex;
			}
		}

		public object Receive()
		{
			try
			{
				return Channel.Receive();
			}
			catch (Exception ex)
			{
				throw a = ex;
			}
		}

		public T Receive<T>()
		{
			return (T)Receive();
		}

		public void Reset()
		{
			a = null;
		}

		public void Dispose()
		{
			lock (this)
			{
				if (Pool != null)
				{
					SyncNode syncNode = Pool;
					Pool = null;
					if (a == null)
					{
						syncNode.a(this);
					}
					else
					{
						syncNode.a(a);
					}
				}
			}
		}
	}

	private Exception m_a;

	private Timer b;

	private Queue<Connection> c = new Queue<Connection>();

	private Type d;

	public string[] GroupNodes;

	private bool e;

	private bool f;

	[CompilerGenerated]
	private string g;

	[CompilerGenerated]
	private string h;

	[CompilerGenerated]
	private int i;

	[CompilerGenerated]
	private int j;

	[CompilerGenerated]
	private int k;

	[CompilerGenerated]
	private string l;

	[CompilerGenerated]
	private int m;

	public string GroupName
	{
		[CompilerGenerated]
		get
		{
			return g;
		}
		[CompilerGenerated]
		set
		{
			g = value;
		}
	}

	public string Host
	{
		[CompilerGenerated]
		get
		{
			return h;
		}
		[CompilerGenerated]
		set
		{
			h = value;
		}
	}

	public int Port
	{
		[CompilerGenerated]
		get
		{
			return i;
		}
		[CompilerGenerated]
		set
		{
			i = value;
		}
	}

	public int DetectTime
	{
		[CompilerGenerated]
		get
		{
			return j;
		}
		[CompilerGenerated]
		set
		{
			j = value;
		}
	}

	public int TimeOut
	{
		[CompilerGenerated]
		get
		{
			return k;
		}
		[CompilerGenerated]
		set
		{
			k = value;
		}
	}

	public string Name
	{
		[CompilerGenerated]
		get
		{
			return l;
		}
		[CompilerGenerated]
		set
		{
			l = value;
		}
	}

	public int MaxConnections
	{
		[CompilerGenerated]
		get
		{
			return m;
		}
		[CompilerGenerated]
		set
		{
			m = value;
		}
	}

	public Exception LastError => this.m_a;

	public int Connections => c.Count;

	public bool Available => e;

	public bool IsDisposed => f;

	public SyncNode(string host, int port, int maxconnections)
	{
		Host = host;
		Port = port;
		DetectTime = 10;
		TimeOut = -1;
		MaxConnections = maxconnections;
	}

	public Connection Pop()
	{
		Connection connection = null;
		if (!Available)
		{
			return connection;
		}
		for (int i = 1; i < 10; i++)
		{
			lock (this)
			{
				if (c.Count > 0)
				{
					connection = c.Dequeue();
					connection.Reset();
					connection.Pool = this;
					return connection;
				}
			}
			Thread.Sleep(1);
		}
		return connection;
	}

	internal void a(Connection A_0)
	{
		lock (this)
		{
			if (A_0 != null)
			{
				c.Enqueue(A_0);
			}
		}
	}

	public RESULT Send<RESULT>(object data)
	{
		return (RESULT)Send(data);
	}

	public object Send(object data)
	{
		Connection connection = Pop();
		if (connection == null)
		{
			throw NetTcpException.ConnectionIsNotAvailable();
		}
		using (connection)
		{
			return connection.Send(data);
		}
	}

	public void Connect<T>() where T : ISyncChannel, new()
	{
		if (b == null)
		{
			b = new Timer(a, null, -1, DetectTime * 1000);
		}
		d = typeof(T);
		ThreadPool.QueueUserWorkItem(a);
	}

	private void a(bool A_0)
	{
		lock (this)
		{
			e = A_0;
			if (Available)
			{
				if (b != null)
				{
					b.Change(-1, DetectTime * 1000);
				}
			}
			else if (b != null)
			{
				b.Change(DetectTime * 1000, DetectTime * 1000);
			}
		}
	}

	private void a(object A_0)
	{
		if (b != null)
		{
			b.Change(-1, DetectTime * 1000);
		}
		try
		{
			do
			{
				Connection a_ = a();
				a(a_);
			}
			while (c.Count < MaxConnections);
			a(A_0: true);
		}
		catch (Exception a_2)
		{
			a(a_2);
		}
	}

	private Connection a()
	{
		Connection connection = new Connection();
		ISyncChannel syncChannel = (ISyncChannel)Activator.CreateInstance(d);
		syncChannel.Timeout = TimeOut;
		syncChannel.Connect(Host, Port);
		connection.Channel = syncChannel;
		return connection;
	}

	internal void a(Exception A_0)
	{
		this.m_a = A_0;
		lock (this)
		{
			while (c.Count > 0)
			{
				c.Dequeue().Channel.Dispose();
			}
		}
		a(A_0: false);
	}

	public void Dispose()
	{
		lock (this)
		{
			if (!f)
			{
				f = true;
				while (c.Count > 0)
				{
					c.Dequeue().Channel.Dispose();
				}
			}
		}
	}
}
